import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import warnings
warnings.filterwarnings('ignore')

# === 1. 数据获取 ===
filepath = 'D:\\7-Deep learning\\temps.csv'
features = pd.read_csv(filepath)

# === 2. 数据预处理 ===
# ==1== 处理时间数据，将年月日组合在一起
import datetime
years = features['year']
months = features['month']
days = features['day']
dates = [datetime.datetime.strptime(f"{year}-{month}-{day}", '%Y-%m-%d') for year, month, day in zip(years, months, days)]

# ==2== 对字符型数据 one-hot 编码
features = pd.get_dummies(features)

# === 3. 特征值和目标值划分 ===
targets = np.array(features['actual'])
features = features.drop(['actual', 'friend'], axis=1)
features = np.array(features)

# === 4. 标准化处理 ===
input_features = preprocessing.StandardScaler().fit_transform(features)

# === 5. 数据划分（随机训练集与测试集）===
X_train, X_test, y_train, y_test, train_indices, test_indices = train_test_split(
    input_features, targets, np.arange(len(dates)), test_size=0.25, random_state=42
)

# 通过索引获取训练集和测试集对应的日期
train_dates = np.array(dates)[train_indices]
test_dates = np.array(dates)[test_indices]

# === 6. keras 构建网络模型 ===
model = tf.keras.Sequential([
    layers.Dense(16, kernel_initializer='random_normal', kernel_regularizer=tf.keras.regularizers.l2(0.01)),
    layers.Dense(32, kernel_initializer='random_normal', kernel_regularizer=tf.keras.regularizers.l2(0.01)),
    layers.Dense(1, kernel_initializer='random_normal', kernel_regularizer=tf.keras.regularizers.l2(0.01))
])

# === 7. 指定优化器 ===
model.compile(optimizer=tf.keras.optimizers.SGD(0.001), loss='mean_squared_error')

# === 8. 网络训练 ===
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=100, batch_size=128)

# === 9. 网络模型结构 ===
model.summary()

# === 10. 模型预测 ===
predict = model.predict(X_test)

# === 11. 可视化测试集预测结果 ===
fig = plt.figure(figsize=(12, 6))
axes = fig.add_subplot(111)

# 测试集真实值：蓝色散点
axes.plot(test_dates, y_test, 'bo', label='Actual')

# 测试集预测值：红色散点
axes.plot(test_dates, predict, 'ro', label='Predict')

# 设置 x 轴
interval = max(1, len(test_dates) // 10)  # 控制标签间隔，确保显示最多 10 个标签
axes.set_xticks(test_dates[::interval])
axes.set_xticklabels(
    [date.strftime('%m-%d') for date in test_dates[::interval]],  # 格式化日期为 "MM-DD"
    rotation=45,  # 标签旋转
    fontsize=10   # 标签字体大小
)

# 添加图例和布局调整
plt.legend()
plt.tight_layout()
plt.show()
